#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>


void lcd_put_pixel(int x, int y, unsigned int color , unsigned char *buf);

static struct fb_var_screeninfo var; //lcd可变参数

int main(int argc, char *argv[]){

    //打开设备
    int fb_fd = open("/dev/fb0", O_RDWR);
    if(fb_fd < 0){
        printf("open /dev/fb0\n");
        return -1;
    }
    //获取lcd可变参数
    ioctl(fb_fd, FBIOGET_VSCREENINFO, &var);
    //映射Fremabuffer
    int screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //frame buffer size
    unsigned char *buf = mmap(NULL, screen_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd,0);
    if(buf == (unsigned char *)-1){
        printf("can't mmap\n");
        return -1;
    }

    /*清屏: 全部设为白色*/
    memset(buf, 0xff, screen_size);
    
    /*随便设置100个红色*/
    while(1)
    {
        for(int i = 0; i < 100; i++){
            lcd_put_pixel(var.xres/2+i, var.yres/2+i, 0x00ff0000, buf);
        }
        sleep(1);
         for(int i = 0; i < 100; i++){
            lcd_put_pixel(var.xres/2-i, var.yres/2-i, 0x00ff0000, buf);
        }
        sleep(1);
        for(int i = 0; i < 100; i++){
            lcd_put_pixel(var.xres/2+i, var.yres/2-i, 0x00ff0000, buf);
        }
        sleep(1);
        for(int i = 0; i < 100; i++){
            lcd_put_pixel(var.xres/2-i, var.yres/2+i, 0x00ff0000, buf);
        }        
        sleep(1);
        memset(buf, 0xff, screen_size);
        sleep(1);
    }


    /*关闭设备*/
    munmap(buf, screen_size);
    close(fb_fd);
    return 0;
}

/*描点函数*/
void lcd_put_pixel(int x, int y, unsigned int color , unsigned char *buf){

    unsigned char *pen_8 = buf + (var.xres*var.bits_per_pixel/8)*y + x*var.bits_per_pixel/8;
    unsigned short *pen_16;
    unsigned int *pen_32;

    unsigned int red, green, blue;

    pen_16 = (unsigned short *)pen_8;
    pen_32 = (unsigned int *)pen_8;

    // printf("color: %d\n", var.bits_per_pixel/8);

    switch(var.bits_per_pixel){
        case 8:{
            *pen_8 = color;
            break;
        }
        case 16:{
            /*565*/
            red = (color >> 16) & 0xff;
            green = (color >> 8) & 0xff;
            blue = (color >> 0) & 0xff;
            color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);
            *pen_16 = color;
            break;
        }
        case 32:{
            *pen_32 = color;
            break;
        }
        default:{
            printf("can't surport %dbpp\n",var.bits_per_pixel);
            break;
        }
    }
}
